/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://gitee.com/newgolo/embedme.git
 * Copyright 2014~2020 @ ShenZhen ,China
*******************************************************************************/
#ifndef __TIMER_H__
#define __TIMER_H__

#include <time.h>
#include <iostream>
#include <list>
#include "libemb/BaseType.h"
#include "libemb/Thread.h"
#include "libemb/ThreadUtil.h"
#include "libemb/DateTime.h"

/**
 * @file  Timer.h   
 * @brief 定时器
 */
namespace libemb{

/**
 * @class TimerListener
 * @brief Timer定时器监听器接口	
 */
class TimerListener{
public:
    TimerListener(){};
    virtual ~TimerListener(){};
    /**
     * @brief 定时回调函数
     * @param timerID 
     */
    virtual void onTimer(int timerID)=0;
};

/**
 * @class Timer
 * @brief 定时器类
 */
class Timer{
DECL_CLASSNAME(Timer)
public:
	Timer(const TimerListener& listener,int timerID);
	~Timer();
    /**
     * @brief 开启定时器
     * @param seconds 
     * @param repeats <0:一直重复; =0:不重复,>0:重复repeats次
     * @return true 
     * @return false 
     */
	bool start(int seconds, int repeats=-1);
    /**
     * @brief 停止定时器
     */
	void stop();
    /**
     * @brief 获取定时器id
     * @return int 
     */
	int id(){return m_timerID;}
private:
	void checkAlarm();
private:
	friend class TimerManager;
	TimerListener* m_listener{nullptr};
	Time m_alarmTime;
	int m_timerID{0};
	int m_repeats{0};
	int m_interval{0};
	bool m_startFlag{false};
};

/**
 * @class TimerManager
 * @brief 定时器管理器
 */
class TimerManager:public Runnable,public Singleton<TimerManager>{
DECL_CLASSNAME(TimerManager)
DECL_SINGLETON(TimerManager)
public:
	~TimerManager();
    /**
     * @brief 注册定时器
     * @param timer 
     * @return true 
     * @return false 
     */
	bool registerTimer(const Timer& timer);
    /**
     * @brief 注销定时器
     * @param timer 
     * @return true 
     * @return false 
     */
    bool unregisterTimer(const Timer& timer);
private:
	void run(Thread& thread);
private:
	Mutex m_tmrlstMutex;
	std::unique_ptr<Thread> m_thread{nullptr};
    std::list<Timer*> m_timerList;
	bool m_startFlag{false};
};

/**
 *  @class  RTimer
 *  @brief  实时定时器类(每个定时器独占一个线程)
 */
class RTimer:public Runnable{
DECL_CLASSNAME(RTimer)
public:
	/**
	 * @brief RTimer构造函数
	 * @param listener 定时器监听器
	 * @param id 定时器ID
	 */
    RTimer(const TimerListener& listener,int id);
    ~RTimer();
	/**
	 * @brief 启动定时器
	 * @param usTimeout 定时时间
	 * @param usTick 时间颗粒度(必须要小于usTimeout,颗粒度越小,定时精度越高,但CPU负荷越重)
	 * @param repeat 是否重复
	 * @return true 启动成功
	 * @return false 启动失败
	 */
    bool start(int usTimeout,int usTick,bool repeat=false);
	/**
	 * @brief 停止定时器
	 */
    void stop();
	/**
	 * @brief 获取定时器ID
	 * @return int 定时器ID
	 */
    int id(){return m_timerID;}
private:
    void run(Thread& thread);
private:
	std::unique_ptr<Thread> m_thread{nullptr};
	TimerListener* m_listener{nullptr};
	bool m_repeat{false};
	int m_timerID{0};
    int m_usInterval{0};
	int m_usTick{1};
};

#if 0   //使用EventPoller替代
/**
 * @class EventTimer
 * @brief 事件定时器类
 */
class EventTimer:public TimerListener{
DECL_CLASSNAME(EventTimer)
public:	
	/**
	 * @brief 事件定时器
	 * @param usCheck 事件检查间隔时间(单位:us)
	 * @param evtMask 事件掩码(屏蔽事件位,如:0x00FFFFFF表示检查事件时忽略最高八位,默认为0xFFFFFFFF)
	 */
	EventTimer(int usCheck,int evtMask=-1);
	virtual ~EventTimer();
	/**
	 * @brief 清空事件
	 * @note 在等待事件之前清除事件,防止事件重复
	 */
	void clearEvent();
	/**
	 * @brief 等待事件
	 * @param eventList 等待的事件列表 
	 * @param usTimeout 等待的超时时间
	 * @return int 超时返回RC_TIMEOUT,错误返回RC_ERROR,不等待返回RC_OK,等到事件返回事件值(大于0)
 	 * @note 事件值必须大于0,usTimeout取值: -1:一直等待,0:不等待,>0:等待时间
	 */
	int waitEvent(std::vector<int> eventList,int usTimeout);
	/**
	 * @brief 报告事件
	 * @param event 发现的事件(>0)
	 * @note 事件值必须大于0 
	 */
	void meetEvent(int event);
private:
	void onTimer(int timerID);
private:
	std::unique_ptr<RTimer> m_timer;
	std::vector<int> m_eventList;
	MutexCond m_cond;
	bool m_isStart{false};
	bool m_isTimeout{false};
	int m_event{-1};
	int m_evtMask{-1};
	int m_usCheck{100};
};
#endif
}
#endif
